package com.softaria.spkiller.dependencies;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import com.softaria.spkiller.layers.LayerIdentifier;
import com.softaria.spkiller.layers.LayerIdentifierImpl;
import com.softaria.spkiller.layers.classificator.Classificator;
import com.softaria.spkiller.metadata.ClassIdentifier;
import com.softaria.spkiller.metadata.ClassIdentifierImpl;
import com.softaria.spkiller.metadata.ClassMetaData;

public class MockFactory implements DependencyGraph, Classificator {
	
	private Map<ClassIdentifier, LayerIdentifier> layers = new HashMap<ClassIdentifier, LayerIdentifier>();
	private Map<ClassIdentifier, Collection<ClassIdentifier>> usedBy = new HashMap<ClassIdentifier, Collection<ClassIdentifier>>();
	
	public MockFactory(InputStream is) throws JAXBException {
		JAXBContext jaxbContext = JAXBContext.newInstance("com.softaria.spkiller.dependencies");
		
		@SuppressWarnings("unchecked")
		JAXBElement<Graph> o = (JAXBElement<Graph>) jaxbContext.createUnmarshaller().unmarshal(is);
		
		Graph g = o.getValue();
		
		List<Layer> layers = g.getLayer();
		
		for(Layer layer:layers) {
			processLayer(layer);
		}
		
	}

	private void processLayer(Layer layer) {
		List<ClassElement> classes = layer.getClassElement();
		
		for(ClassElement classElement:classes) {
			processClass(layer,classElement);
		}
		
	}

	private void processClass(Layer layer, ClassElement classElement) {
		
		ClassIdentifier classID = new ClassIdentifierImpl(classElement.getId());
		
		layers.put(classID,new LayerIdentifierImpl(layer.getName()));
		
		List<Object> subs = classElement.getClassElementOrClassReference();
		
		List<ClassIdentifier> used = new ArrayList<ClassIdentifier>();
		
		for(Object sub:subs) {
			if(sub instanceof ClassElement) {
				ClassElement subElement = (ClassElement)sub;
				processClass(layer, subElement);
				used.add(new ClassIdentifierImpl(subElement.getId()));
			} else {
				if(sub instanceof String) {
					used.add(new ClassIdentifierImpl((String)sub));
				}
			}
		}
		
		usedBy.put(classID,used);
	}

	@Override
	public LayerIdentifier classificate(ClassIdentifier classID) {
		return layers.get(classID);
	}
	
	@Override
	public LayerIdentifier classificate(ClassMetaData metaData) {
		return classificate(metaData.getIdentifier());
	}

	@Override
	public Collection<ClassIdentifier> getAllClasses() {
		return layers.keySet();
	}

	@Override
	public Collection<ClassIdentifier> getUsedClasses(ClassIdentifier user) {
		return usedBy.get(user);
	}

	
	
	
}
